package be.scond.cartpool;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.List;
import javax.servlet.http.*;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import be.scond.cartpool.API.GroupApi;
import be.scond.cartpool.API.ShoppingListApi;
import be.scond.cartpool.API.UserApi;
import be.scond.cartpool.exceptions.GroupDoesNotExistException;
import be.scond.cartpool.exceptions.GroupExistsException;
import be.scond.cartpool.exceptions.GroupPassIncorrectException;
import be.scond.cartpool.exceptions.UserExistsException;
import be.scond.cartpool.exceptions.UserNotFoundException;
import be.scond.cartpool.model.Group;
import be.scond.cartpool.model.ShoppingList;
import be.scond.cartpool.model.User;
import be.scond.utils.CheckEmail;

public class CartpoolAPIServlet extends HttpServlet {
	
	static final long serialVersionUID = 1;
	

	
	public static final String ACTION_REGISTER_GROUP = "ACTION_REGISTER_GROUP"; 
	public static final String ACTION_CONFIRM_GROUP = "ACTION_CONFIRM_GROUP"; 
	public static final String ACTION_DELETE_GROUP = "ACTION_DELETE_GROUP"; 
	
	public static final String ACTION_REGISTER_USER_WITH_GROUP = "ACTION_REGISTER_USER_WITH_GROUP";
	public static final String ACTION_CONFIRM_USER = "ACTION_CONFIRM_USER"; 
	public static final String ACTION_DELETE_USER = "ACTION_DELETE_USER"; 
	
	public static final String ACTION_DELETE_SHOPPINGLIST = "ACTION_DELETE_SHOPPINGLIST"; 
	
	public static final String ACTION_RETURN_GROUPS = "ACTION_RETURN_GROUPS"; 
	public static final String ACTION_RETURN_USERS = "ACTION_RETURN_USERS"; 
	public static final String ACTION_RETURN_SHOPPINGLISTS = "ACTION_RETURN_SHOPPINGLISTS";
	public static final String ACTION_RETURN_DEBUGLIST = "ACTION_RETURN_DEBUGLIST"; 
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		
	}
	
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		String action = req.getParameter("action");
		resp.setCharacterEncoding("UTF-8");
		resp.setContentType("text/xml");
		
		
		String respons = "<data>";
		
		String groupName = req.getParameter("groupName");
		String userName = req.getParameter("userName");
		String email = req.getParameter("email");
		String password = req.getParameter("password");
	
		
		if(action.equals(ACTION_REGISTER_GROUP)){
			if(CheckEmail.check(email)){
				try {
					Group newGroup = GroupApi.registerGroup(groupName, userName, email, password);
					respons += "<succes>registering of group with name "+groupName+" succeeded</succes>";						
					respons += newGroup.toVerbalXmlString();				
				} catch (GroupExistsException e) {
					respons += "<error>The group with name: " + groupName + " already exists</error>";
				}				
			}else{
				respons += "<error>"+email+" is not a valid email adress</error>";
			}
		}else
					
			
		if(action.equals(ACTION_CONFIRM_GROUP)){
			try {
				GroupApi.confirmGroup(groupName);
				respons += "<succes>confirmation of group with name "+groupName+" succeeded</succes>";						
			} catch (GroupDoesNotExistException e) {
				respons += "<error>confirmation of group with name "+groupName+" failed, " + groupName + " does not exist</error>";
			}
		}else
			
		
		if(action.equals(ACTION_DELETE_GROUP)){
			try {
				GroupApi.deleteGroup(groupName);
				respons += "<succes>"+groupName+" has been deleted</succes>";
			} catch (GroupDoesNotExistException e) {
				respons += "<error>delete failed, " + groupName + " does not exist</error>";			
			}
		}else
			
		
		if(action.equals(ACTION_CONFIRM_USER)){
			respons += "<error>ACTION_CONFIRM_USER is not implemented yet.</error>";
		}else
			
			
		if(action.equals(ACTION_DELETE_USER)){
			String userKey = req.getParameter("userKey");
			try {
				UserApi.deleteUser(userKey);
				respons += "<succes>user with key "+userKey+" has been deleted</succes>";
			} catch (UserNotFoundException e) {
				respons += "<error>delete failed, user with key " + userKey + " not found</error>";			
			}
		}else
			
		
		if(action.equals(ACTION_REGISTER_USER_WITH_GROUP)){	
			String groupPass = req.getParameter("groupPass");
			if(CheckEmail.check(email)){
				try {
					User u = GroupApi.registerUserWithGroup(userName, email, groupName, groupPass, password);
					respons += "<succes>registered succesfully</succes>";								
					respons += u.toXmlString();								
				} catch (UserExistsException e) {
					respons += "<error>Failed to register user with group "+groupName+", email: " + email + " or userName: "+userName+" already exists for this group</error>";
				}catch (GroupDoesNotExistException e) {
					respons += "<error>Failed to register user "+userName+" with group "+groupName+" failed, " + groupName + " does not exist</error>";
				}catch (GroupPassIncorrectException e) {
					respons += "<error>Failed to register user with group "+groupName+", The provided groupKey was incorrect</error>";
				}
			}else{
				respons += "<error>"+email+" is not a valid email adress</error>";
			}			
		}else
			
			
		if(action.equals(ACTION_RETURN_GROUPS)){
			List<Group> groups = GroupApi.getAllGroups();
			respons += "<succes>groups found</succes>";		
			for (Group group : groups) {
				respons += group.toSimpleXmlString();
			}
		}else

			
		if(action.equals(ACTION_RETURN_USERS)){
			try {
				List<User> users = UserApi.getAllUsers(groupName);
				respons += "<succes>"+users.size()+" users where found</succes>";			
				for (User user : users) {
					respons += user.toXmlString();
				}				
			} catch (GroupDoesNotExistException e) {
				respons += "<error>Group "+groupName+" to return users from is not found</error>";
			}
		}else
			
		if(action.equals(ACTION_RETURN_SHOPPINGLISTS)){
			int fromRange = Integer.parseInt(req.getParameter("from"));
			int toRange = Integer.parseInt(req.getParameter("to"));
		
			try {
				List<ShoppingList> shoppingLists = ShoppingListApi.getShoppingLists(groupName, fromRange, toRange);				
				respons += "<succes>"+shoppingLists.size()+" shoppingLists where found</succes>";			
				for (ShoppingList shoppingList : shoppingLists) {
					respons += shoppingList.toXmlString();
				}				
			} catch (GroupDoesNotExistException e) {
				respons += "<error>Group "+groupName+" to return shoppingLists from is not found</error>";
			}
		}else {
			respons += "<error>Action not found</error>";
		}
		
		respons += "</data>";

		
		// use a transformer to format the string into readable xml.
		String xmlString = "<error>xml transformation of the respons failed</error>";
		try {
			Transformer transformer = TransformerFactory.newInstance().newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
			transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
			//initialize StreamResult with File object to save to file
			StreamResult result = new StreamResult(new StringWriter());
			transformer.transform(new StreamSource(new StringReader(respons)), result);
			xmlString = result.getWriter().toString();			
		} catch (TransformerConfigurationException e) {
			// TODO: handle exception
		} catch (TransformerException e) {
			// TODO: handle exception
		}
		
		resp.getWriter().print(xmlString);
	}
}